#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <ctype.h>
#include <limits.h>
#include "process.h"

const char* nombre_programa;

/**
 * Interpreta las opciones recibidas y llama a la función
 * que compara los archivos.
 */
int parser(int argc, char **argv);

/**
 * Indica si el string recibido es un número.
 */
int is_num(char* s);

int main(int argc, char* argv[]) {
	return parser(argc, argv);
}

void print_version() {
	fprintf(stdout, "%s diff (GNU diffutils) 1.0\n", nombre_programa);
	fprintf(stdout, "Copyright (C) 2011 Free Software Foundation, Inc.\n");
	fprintf(stdout, "Writen by Veronica Bukaczewski y Ariel George.\n");
}

void print_help() {
	fprintf(stdout, "Usage: \n");
	fprintf(stdout, "  %s [options] from-file to-file\n", nombre_programa);
	fprintf(stdout, "  %s - find differences between two files\n",
			nombre_programa);
	fprintf(stdout, "  %s - find differences between two files\n",
			nombre_programa);
	fprintf(stdout, "Options:\n");
	fprintf(stdout, "  -v, --version   Print version and quit.\n");
	fprintf(stdout, "  -h, --help      Print this information and quit.\n");
	fprintf(stdout, "  -o, --output    Specifies the output file.\n");
	fprintf(stdout, "  -m, --max       Shows the first m differences.\n");
}

void print_error() {
	fprintf(stderr, "%s: Try «%s --help» for more information.\n",
			nombre_programa, nombre_programa);
}

int parser(int argc, char **argv) {
	/* Valor de retorno de la salida del programa */
	int valor_retorno = EXIT_SUCCESS;

	/* Guardar el nombre del programa */
	nombre_programa = argv[0];

	/* Una cadena que lista las opciones cortas válidas */
	const char* const op_cortas = "vhm:o:";

	/* Una estructura de varios arrays describiendo los valores largos */
	const struct option op_largas[] = { { "version", 0, NULL, 'v' }, { "help",
			0, NULL, 'h' }, { "output", 1, NULL, 'o' },
			{ "max", 1, NULL, 'm' }, { NULL, 0, NULL, 0 } };

	/* Llamamos a la función getopt */
	int c;
	int max = INT_MAX;
	FILE* output = stdout;
	while ((c = getopt_long(argc, argv, op_cortas, op_largas, NULL)) != -1) {
		switch (c) {
		case 'v': /* -v o --version */
			print_version();
			return EXIT_SUCCESS;
		case 'h': /* -h o --help */
			print_help();
			return EXIT_SUCCESS;
		case 'o': /* -o o --output */
			output = fopen(optarg, "w");
			if (!output) {
				perror("Wrong output");
				return EXIT_FAILURE;
			}
			break;
		case 'm': /* -m o --max */
			if (!is_num(optarg)) {
				print_help();
				return EXIT_FAILURE;
			}
			max = atoi(optarg);
			break;
		case '?': /* opción no valida */
			print_error();
			return EXIT_FAILURE;
		case -1: /* No hay más opciones */
			break;
		default:
			return EXIT_FAILURE;//inesperado
		}
	}

	//Faltan los archivos
	if (argc - optind != 2) {
		print_help();
		return EXIT_FAILURE;
	}

	//si llegamos acá es una invocación válida.
	valor_retorno = process_files(argv[optind], argv[optind + 1], output, max);
	if (valor_retorno == EXIT_FAILURE) {
		perror("Wrong file");
	}

	if (output != stdout)
		fclose(output);

	return valor_retorno;
}

int is_num(char* s) {
	while (*s != '\0') {
		if (!isdigit((unsigned char)*s))
			return 0;
		++s;
	}
	return 1;
}
